package com.yifi.config;

import cn.hutool.core.util.StrUtil;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.lastb7.swagger.handler.SwaggerHandler;
import com.lastb7.swagger.plugin.SwaggerPlugin;
import com.lastb7.swagger.routes.SwaggerRoutes;
import com.yifi.common.plugins.IoTDB.IoTDBPlugin;
import com.yifi.common.plugins.JwFlowPlugin;
import com.yifi.common.plugins.influxDB.InfluxDBPlugin;
import com.yifi.common.vo.CommonHttpCode;
import com.yifi.common.vo.CommonRes;
import com.yifi.service.CronJob;
import org.apache.log4j.Logger;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.core.JFinal;
import com.jfinal.ext.handler.ContextPathHandler;
import com.jfinal.ext.handler.UrlSkipHandler;
import com.jfinal.json.FastJsonFactory;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.dialect.AnsiSqlDialect;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.dialect.OracleDialect;
import com.jfinal.plugin.activerecord.dialect.PostgreSqlDialect;
import com.jfinal.plugin.activerecord.dialect.SqlServerDialect;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.druid.DruidStatViewHandler;
import com.jfinal.render.ViewType;
import com.jfinal.template.Engine;
import com.yifi.common.constant.ConstantInit;
import com.yifi.common.handler.GlobalHandler;
import com.yifi.common.handler.XssHandler;
import com.yifi.common.model.Syslog;
import com.yifi.common.utils.DataBase;
import com.yifi.common.utils.ToolDataBase;
import com.yifi.common.utils.ToolString;
import com.yifi.system.domain.MisUser;
import com.yifi.system.service.CronService;

import cn.hutool.cron.CronUtil;

/**
 * API引导式配置
 */
public class JFWebConfig extends JFinalConfig {

	private static Logger log = Logger.getLogger(JFinalConfig.class);

	static Prop p;

	/**
	 * PropKit.useFirstFound(...) 使用参数中从左到右最先被找到的配置文件
	 * 从左到右依次去找配置，找到则立即加载并立即返回，后续配置将被忽略
	 */
	static void loadConfig() {
		if (p == null) {
			p = PropKit.useFirstFound("jdbc.properties");
		}
	}

	/**
	 * 配置常量
	 */
	public void configConstant(Constants me) {
		log.info("configConstant 缓存 properties");
		loadConfig();
		log.info("configConstant 设置是否开发模式");
		me.setDevMode(PropKit.getBoolean(ConstantInit.config_devMode, true));

		log.info("configConstant 设置字符集");
		me.setEncoding(ToolString.encoding);

		me.setViewType(ViewType.JFINAL_TEMPLATE);
		// Json配置
		me.setJsonFactory(FastJsonFactory.me());
		// 开启依赖注入
		me.setInjectDependency(true);
		// 配置对超类中的属性进行注入
		me.setInjectSuperClass(true);

		me.setBaseUploadPath(p.get("path_upload"));
		me.setBaseDownloadPath(p.get("path_upload"));
		me.setMaxPostSize(1024 * 1024 * 200);

		me.setDenyAccessJsp(false);

		// 配置 404、500 页面
		me.setError404View("/common/404.html");
		me.setError500View("/common/500.html");

	}

	/**
	 * 配置路由
	 */
	public void configRoute(Routes routes) {

		if (log.isInfoEnabled())
			log.info("configRoute 注解注册路由");

		routes.add(new Routes() {
			public void config() {
				this.setBaseViewPath("/templates");
				this.scan("com.yifi.module.");
			}
		});
		routes.add(new Routes() {
			public void config() {
				this.setBaseViewPath("/templates");
				this.scan("com.yifi.system.");
			}
		});

		routes.add(new SwaggerRoutes());

	}

	public static DruidPlugin createDruidPlugin() {
		DataBase db = ToolDataBase.getDbInfo();
		String driverClass = db.getDriverClass();
		String jdbcUrl = db.getJdbcUrl();
		String username = db.getUserName();
		String password = db.getPassWord();
		return new DruidPlugin(jdbcUrl, username, password, driverClass);
	}

	/**
	 * 配置插件
	 */
	public void configPlugin(Plugins plugins) {

		log.info("注册paltform ActiveRecordPlugin");
		log.info("configPlugin 配置Druid数据库连接池连接属性");
		DataBase db = ToolDataBase.getDbInfo();

		if (log.isInfoEnabled())
			log.info("configPlugin 配置Druid数据库连接池连接属性");
		DruidPlugin druidPlugin = createDruidPlugin(); // new DruidPlugin(jdbcUrl,username,password,driverClass);

		if (log.isInfoEnabled())
			log.info("configPlugin 配置Druid数据库连接池大小");
		druidPlugin.set(db.getInitialSize(), db.getMinIdle(), db.getMaxActive());

		if (log.isInfoEnabled())
			log.info("configPlugin 配置Druid数据库连接池过滤器配制");
		druidPlugin.addFilter(new StatFilter());
		WallFilter wall = new WallFilter();
		String db_type = db.getType();
		wall.setDbType(db_type);
		WallConfig config = new WallConfig();
		config.setFunctionCheck(false); // 支持数据库函数
		wall.setConfig(config);
		druidPlugin.addFilter(wall);

		ActiveRecordPlugin arpMain = new ActiveRecordPlugin(druidPlugin);

		// arp.setTransactionLevel(4);//默认事务隔离级别4
		boolean devMode = Boolean.parseBoolean(PropKit.get(ConstantInit.config_devMode));
		arpMain.setDevMode(devMode); // 设置开发模式
		arpMain.setShowSql(false); // 是否显示SQL
		arpMain.setContainerFactory(new CaseInsensitiveContainerFactory(true)); // 大小写不敏感

		log.info("configPlugin 数据库类型判断");
		if (db_type.equals(ConstantInit.db_type_postgresql)) {
			log.info("configPlugin 使用数据库类型是 postgresql");
			arpMain.setDialect(new PostgreSqlDialect());

		} else if (db_type.equals(ConstantInit.db_type_mysql)) {
			log.info("configPlugin 使用数据库类型是 mysql");
			arpMain.setDialect(new MysqlDialect());

		} else if (db_type.equals(ConstantInit.db_type_oracle)) {
			log.info("configPlugin 使用数据库类型是 oracle");
			arpMain.setDialect(new OracleDialect());

		} else if (db_type.equals(ConstantInit.db_type_sqlserver)) {
			log.info("configPlugin 使用数据库类型是 sqlserver");
			arpMain.setDialect(new SqlServerDialect());

		} else if (db_type.equals(ConstantInit.db_type_db2)) {
			log.info("configPlugin 使用数据库类型是 db2");
			// //连接验证语句
			arpMain.setDialect(new AnsiSqlDialect());
		}

		// 注册表
		arpMain.addMapping("pt_syslog", Syslog.class);
		arpMain.addMapping("mis_user", MisUser.class);

		if (log.isInfoEnabled())
			log.info("configPlugin 添加druidPlugin插件");
		plugins.add(druidPlugin);

		log.info("configPlugin 注册ActiveRecordPlugin插件");
		plugins.add(arpMain);

		//ehcache缓存插件
		plugins.add(new EhCachePlugin());


		//工作流引擎插件
		JwFlowPlugin jwflowPlugin=new JwFlowPlugin(druidPlugin);
		plugins.add(jwflowPlugin);
	}

	/**
	 * 配置全局拦截器
	 */
	public void configInterceptor(Interceptors me) {

	}

	/**
	 * 配置处理器
	 */
	public void configHandler(Handlers me) {
		log.info("configHandler 全局配置处理器，记录日志和request域值处理");
		me.add(new GlobalHandler());

		me.add(new DruidStatViewHandler("/druid"));

		me.add(new XssHandler("ctx"));
		me.add(new ContextPathHandler("ctx"));

	}

	/**
	 * 建议使用 JFinal 手册推荐的方式启动项目 运行此 main 方法可以启动项目，此main方法可以放置在任意的Class类定义中，不一定要放于此
	 */
	public static void main(String[] args) {

		JFinal.start("WebRoot", 80, "/", 5);
	}

	@Override
	public void configEngine(Engine engine) {
		// TODO Auto-generated method stub

		String ctx = JFinal.me().getContextPath();
		engine.addSharedObject("ctx", ctx);

		engine.addSharedFunction("/common/_admin_layout.html");

		engine.addSharedStaticMethod(WebShareFunctions.class);
		// 配置极速模式，性能提升 13%
		engine.setDevMode(true);
		Engine.setFastMode(true);
	}

	@Override
	public void onStart() {
		if (p.getBoolean("jobtask")) {
			// 从数据库中查找可使用的定时任务方法动态加入
			CronService.addCrons();
			// 支持秒级别定时任务
			CronUtil.setMatchSecond(true);
			CronUtil.start();
		}
		super.onStart();
	}

	@Override
	public void onStop() {

		if (p.getBoolean("jobtask")) {
			CronUtil.stop();
		}
		super.onStop();
	}
}
